﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using CodeStash.Common.DataAccess.EntityFramework;
using CodeStash.Common.DataAccess.Repository;
using CodeStash.Common.DataAccess.UnitOfWork;
using CodeStash.Common.Enums;
using CodeStash.Models.Snippet;
using CodeStash.Services;
using CodeStash.Utils;




namespace CodeStash.Controllers
{
    public class ReadonlyController : Controller
    {

        private readonly ILoggerService loggerService;
        private readonly IRepository<Language> languageRepository;
        private readonly IRepository<CodeCategory> categoryRepository;
        private readonly IRepository<Grouping> groupingRepository;
        private readonly IRepository<CodeSnippet> codeSnippetRepository;
        private readonly IRepository<CodeTag> codeTagRepository;
        private readonly IUnitOfWork unitOfWork;



        public ReadonlyController(
            ILoggerService loggerService, 
            IRepository<Language> languageRepository, 
            IRepository<CodeCategory> categoryRepository,
            IRepository<Grouping> groupingRepository,
            IRepository<CodeSnippet> codeSnippetRepository,
            IRepository<CodeTag> codeTagRepository,
            IUnitOfWork unitOfWork)
        {
            this.loggerService = loggerService;
            this.languageRepository = languageRepository;
            this.categoryRepository = categoryRepository;
            this.groupingRepository = groupingRepository;
            this.codeSnippetRepository = codeSnippetRepository;
            this.codeTagRepository = codeTagRepository;
            this.unitOfWork = unitOfWork;
        }


        [HttpGet]
        public ActionResult Display(int id)
        {
            List<CodeSnippet> allSnippetsInGroup = new List<CodeSnippet>();
            Dictionary<int, bool> snippetPublicOrMineLookup = new Dictionary<int, bool>();
            bool truncated = false;

            using (unitOfWork)
            {
                codeSnippetRepository.EnrolInUnitOfWork(unitOfWork);
                languageRepository.EnrolInUnitOfWork(unitOfWork);
                groupingRepository.EnrolInUnitOfWork(unitOfWork);
                categoryRepository.EnrolInUnitOfWork(unitOfWork);

                CodeSnippet requestedSnippet = codeSnippetRepository.FindBy(x => x.CodeSnippetId == id).SingleOrDefault();
                if (requestedSnippet != null)
                {
                    allSnippetsInGroup.Add(requestedSnippet);

                    if (requestedSnippet.GroupId.HasValue && requestedSnippet.GroupId > 0)
                    {
                        Grouping grouping = groupingRepository.FindBy(x => x.GroupId == requestedSnippet.GroupId).FirstOrDefault();

                        int countOfsnippetsSameAsRequestedGroupSnippets = codeSnippetRepository.FindByExp(x => x.GroupId.HasValue &&
                            requestedSnippet.GroupId.Value == requestedSnippet.GroupId && x.CodeSnippetId != requestedSnippet.CodeSnippetId).ToList().Count();

                        Func<CodeSnippet, bool> snippetFunc = x => x.GroupId.HasValue &&
                            x.GroupId.Value == requestedSnippet.GroupId &&
                            x.CodeSnippetId != requestedSnippet.CodeSnippetId &&
                            x.Visibility == (int)CodeSnippetVisibility.Public;

                        List<CodeSnippet> sameAsRequestedGroupSnippets =
                                CodeSnippetUtils.TakeAsManySnippetsAsWeCan(ref truncated, codeSnippetRepository,
                                    snippetFunc, countOfsnippetsSameAsRequestedGroupSnippets);

                        allSnippetsInGroup.AddRange(sameAsRequestedGroupSnippets);

                        foreach (CodeSnippet snippet in allSnippetsInGroup)
                        {
                            snippet.Grouping = grouping;
                        }
                    }
                    allSnippetsInGroup = CodeSnippetUtils.AddLanguageCategoryLookups(allSnippetsInGroup, languageRepository, categoryRepository);
                }
                else
                {
                    loggerService.Error(string.Format("Readonly : Could not obtain snippet to display, for snippet Id: {0}", id));
                }
            }

            ReadOnlyDisplaySnippetsViewModel vm =
                new ReadOnlyDisplaySnippetsViewModel(allSnippetsInGroup, truncated, "pablo");
            return View("DisplaySnippets", vm);
        }


      

    }
}
